<?php

namespace App\Providers\Hall;

use Exception;
use Closure;
use Illuminate\Database\QueryException;
use Illuminate\Database\Connection;
use Illuminate\Database\MySqlConnection;
use App\Services\HallDomainService;

class HallMySqlConnection extends MySqlConnection
{

    private static $hallExpression = '';
    private static $insertExpression = '/INSERT\s+?INTO[\s`]+?\w+[\s`]+?\((.+)\)\s+?VALUES\s+?\((.+)\)/is';
    private static $whereExpression = '/WHERE(.*)$/is';

    /**
     * Run a SQL statement.
     *
     * @param  string    $query
     * @param  array     $bindings
     * @param  \Closure  $callback
     * @return mixed
     *
     * @throws \Illuminate\Database\QueryException
     */
    protected function runQueryCallback($query, $bindings, Closure $callback)
    {
        $query = $this->hallInject($query);
        // To execute the statement, we'll simply call the callback, which will actually
        // run the SQL against the PDO connection. Then we can calculate the time it
        // took to execute and log the query SQL, bindings and time in our memory.
        try {
            $result = $callback($query, $bindings);
        } catch (Exception $e) {
            throw new QueryException($query, $this->prepareBindings($bindings), $e);
        }

        return $result;
    }

    private function hallInject($query)
    {
        $table = '';
        // 只处理 SELECT|UPDATE|INSERT|DELETE
        if (preg_match('/^[\s]?((SELECT).+?FROM[\s`]+?([\w\.]+)[\s`]*|(UPDATE)[\s`]+?([\w\.]+)[\s`]+?|(INSERT)\s+?INTO[\s`]+?([\w\.]+)[\s`]+?|(DELETE)\s+?FROM[\s`]+?([\w\.]+)[\s`]+?)/is', $query, $matchs)) {
            $size = count($matchs);
            $table = $matchs[$size - 1];
            $hallKey = config('database.hallKey');
            $exceptTables = config('database.exceptTables');
            // 该表是否需要插入hall_id
            if (in_array($table, $exceptTables)) {
                return $query;
            }
            $hallID = HallDomainService::getHallID();
            if (static::$hallExpression === '') {
                static::$hallExpression = '/[\s`]+?' . $hallKey . '[\s`]+?/';
            }
            $op = strtoupper($matchs[$size - 2]);
            switch ($op) {
                case 'SELECT':
                case 'UPDATE':
                case 'DELETE':
                    // 是否有表别名
                    if (preg_match('/FROM[\s`]+?\w+[\s`]+?(AS[\s`]+?(\w+)[\s`]+?|`(\w+)`)?\s?(LEFT|RIGHT|INNER)?\s?JOIN/is', $query, $m)) {
                        $size = count($m);
                        if ($size == 1) {
                            $as = $table;
                        } elseif ($size < 5) {
                            $as = array_pop($m);
                        } else {
                            if ($m[2] != '') {
                                $as = $m[2];
                            } elseif ($m[3] != '') {
                                $as = $m[3];
                            } else {
                                $as = $table;
                            }
                        }
                        preg_match_all('/ON[\w.`\s]+?=[\s]?[\w.`]+/is', $query, $m);
                        // 最后一个on链接
                        $m = array_pop($m);
                        $last = array_pop($m);
                        $idx = strpos($query, $last);
                        $part = substr($query, $idx);
                        // 是否有where条件
                        if (preg_match(static::$whereExpression, $part, $m)) {
                            $replace = "where `$as`.`$hallKey` = $hallID and $1";
                            $where = $m[1];
                            // 没有$hallKey字段
                            if (!preg_match(static::$hallExpression, $where, $m)) {
                                $part = preg_replace(static::$whereExpression, $replace, $part);
                                $query = substr($query, 0, $idx) . $part;
                            }
                        } else {
                            $query = str_replace($last, "$last where `$as`.`$hallKey` = $hallID ", $query);
                        }
                    } else {
                        // 是否有where条件
                        if (preg_match(static::$whereExpression, $query, $m)) {
                            $replace = "where `$hallKey` = $hallID and $1";
                            $where = $m[1];
                            // 没有$hallKey字段
                            if (!preg_match(static::$hallExpression, $where, $m)) {
                                $query = preg_replace(static::$whereExpression, $replace, $query);
                            }
                        } else {
                            $query = preg_replace('/FROM[\s`]+?\w+[\s`]*(.*)$/is', "from `$table` where `$hallKey` = $hallID $1", $query);
                        }
                    }
                    break;
                case 'INSERT':
                    if (preg_match(static::$insertExpression, $query, $m)) {
                        // 没有$hallKey字段
                        if (!preg_match(static::$hallExpression, $m[1], $n)) {
                            $query = preg_replace(static::$insertExpression, "insert into `$table` (`$hallKey`,$1) values ($hallID,$2)", $query);
                        }
                    } else {
                        throw new Exception('INSERT Format Error!');
                    }
                    break;
            }
        }
        return $query;
    }
}
